package com.dm.cloud.configurations.smspass;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dm.cloud.api.dto.Users;
import com.dm.cloud.dao.UsersDao;
import com.dm.cloud.utils.SpringContextUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;

/**
 * Description:
 * 短信登陆鉴权 Provider，要求实现 AuthenticationProvider 接口
 */
@Slf4j
@Configuration
public class SmsCodeAuthenticationProvider implements AuthenticationProvider {

    private UsersDao usersDao;

    private SmsCodeUserDetailService smsCodeUserDetailService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        SmsCodeAuthenticationToken smsCodeAuthenticationToken = (SmsCodeAuthenticationToken) authentication;

        String mobile = (String) smsCodeAuthenticationToken.getPrincipal();

        usersDao = SpringContextUtils.getBean(UsersDao.class);

        //查询手机号的详细信息
        QueryWrapper<Users> usersQueryWrapper =new QueryWrapper<>();
        usersQueryWrapper.eq("phone_no",mobile).eq("delete_flag",0);

        Users user = usersDao.selectOne(usersQueryWrapper);
        if(null!=user){
            //校验手机收到的验证码和rediss中的验证码是否一致
            smsCodeUserDetailService = SpringContextUtils.getBean(SmsCodeUserDetailService.class);
            UserDetails userDetails = smsCodeUserDetailService.loadUserByPhone(mobile,user);
            //授权通过
            return new SmsCodeAuthenticationToken(userDetails, userDetails.getAuthorities());
        }else{
            throw new BadCredentialsException("该手机号未注册或未绑定账号!");
        }
    }

    /**
     * ProviderManager 选择具体Provider时根据此方法判断
     * 判断 authentication 是不是 SmsCodeAuthenticationToken 的子类或子接口
     */
    @Override
    public boolean supports(Class<?> authentication) {
        return SmsCodeAuthenticationToken.class.isAssignableFrom(authentication);
    }
}